package com.sparkseries.service.impl;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.sparkseries.common.util.exception.BusinessException;
import com.sparkseries.common.util.tool.PasswordStrengthValidator;
import com.sparkseries.dao.SysRoleMapper;
import com.sparkseries.dao.SysUserMapper;
import com.sparkseries.domain.SysUser;
import com.sparkseries.domain.SysUserAuthentication;
import com.sparkseries.domain.vo.SysUserVO;
import com.sparkseries.dto.SysUserAuthenticationDTO;
import com.sparkseries.dto.SysUserDTO;
import com.sparkseries.enums.AuthenticationStatusEnum;
import com.sparkseries.enums.DefaultStatusEnum;
import com.sparkseries.enums.UserNotifyTypeEnum;
import com.sparkseries.service.SysUserService;
import com.sparkseries.common.util.domain.Result;
import com.sparkseries.common.util.tool.ObjectConvertTool;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * 用户管理服务实现
 * TODO 优化参数校验
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl implements SysUserService {
    private final SysUserMapper sysUserMapper;
    private final SysRoleMapper sysRoleMapper;
    private final PasswordEncoder encoder;

    /**
     * 注册用户
     * @param userDTO 用户传输类
     * @return 默认响应类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> register(SysUserDTO userDTO) {
        validateUserDTO(userDTO);
        validUniqueUsername(userDTO);

        // 密码加密 & 对象转换
        userDTO.setPassword(encoder.encode(userDTO.getPassword()));
        SysUser sysUser = convertToSysUser(userDTO);
        sysUser.setId(IdWorker.getId());

        if (sysUserMapper.register(sysUser) <= 0) {
            log.error("用户注册失败，用户信息: {}", userDTO);
            throw new BusinessException("用户注册失败");
        }
        log.info("用户注册成功，用户ID: {}", sysUser.getId());

        // 初始化默认角色
        initializeDefaultRole(sysUser.getId());

        return Result.ok("用户注册成功");
    }

    /**
     * 初始化用户默认角色
     */
    private void initializeDefaultRole(Long userId) {
        if (sysRoleMapper.initUserRole(userId) <= 0) {
            log.error("用户初始默认角色失败，UserID: {}", userId);
            throw new BusinessException("角色初始化失败");
        }
        log.debug("默认角色已成功初始给用户: {}", userId);
    }

    /**
     * 实名认证
     * @param dto 实名信息传输类
     * @return 默认响应类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> userAuthenticate(SysUserAuthenticationDTO dto) {
        validateAuthenticationDTO(dto);

        // 插入认证记录
        SysUserAuthentication auth = ObjectConvertTool.originConvert(dto, SysUserAuthentication.class);
        if (sysUserMapper.insertUserAuthentication(auth) <= 0) {
            log.error("实名认证失败，用户ID: {}", dto.getId());
            throw new BusinessException("实名认证信息保存失败");
        }

        // 更新认证状态
        if (sysUserMapper.updateUserAuthStatus(dto.getId(), AuthenticationStatusEnum.CERTIFIED.getCode()) <= 0) {
            log.error("认证状态更新失败，用户ID: {}", dto.getId());
            throw new BusinessException("认证状态更新失败");
        }

        return Result.ok("认证成功");
    }

    /**
     * 注销用户
     * @param userId 用户ID
     * @return 默认响应类
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Result<?> deleteUser(Long userId) {
        validateUserId(userId);

        // 删除用户主体
        if (sysUserMapper.deleteUser(userId) <= 0) {
            log.error("用户注销失败，用户ID: {}", userId);
            throw new BusinessException("用户注销失败");
        }

        // 清理关联数据
        cleanupUserAssociations(userId);

        log.info("用户注销成功，用户ID: {}", userId);
        return Result.ok("用户注销成功");
    }

    /**
     * 清理用户关联数据（角色绑定/认证信息）
     */
    private void cleanupUserAssociations(Long userId) {
        // 删除角色绑定
        int unbindCount = sysRoleMapper.deleteRoleBindU(userId);
        log.debug("已移除了用户: {}的{}条权限绑定", userId, unbindCount);

        // 删除认证信息
        if (sysUserMapper.deleteUserAuthentication(userId) <= 0) {
            log.warn("没有发现此用户的认证信息: {}", userId);
        }
    }

    /**
     * 修改用户信息
     * @param userDTO 用户传输类
     * @return 默认响应类
     */
    @Override
    public Result<?> updateUser(SysUserDTO userDTO) {
        validateUserDTO(userDTO);
        validateUserId(userDTO.getId());

        SysUser user = convertToSysUser(userDTO);
        if (sysUserMapper.updateUserInfo(user) <= 0) {
            log.error("用户信息修改失败，用户信息: {}", user);
            throw new BusinessException("用户信息修改失败");
        }

        log.info("用户修改成功，用户ID：{}", user.getId());
        return Result.ok("用户信息修改成功");
    }

    /**
     * 修改用户密码
     * @param userId 用户ID
     * @param password 用户密码
     * @return 默认响应类
     */
    @Override
    public Result<?> updateUserPassword(Long userId, String password) {
        validateUserId(userId);
        validatePassword(password);

        if (sysUserMapper.updatePasswordByUserId(userId, encoder.encode(password)) <= 0) {
            log.error("用户密码修改失败，用户ID: {}", userId);
            throw new BusinessException("用户密码修改失败");
        }

        log.info("用户密码修改成功，用户ID: {}", userId);
        return Result.ok("用户密码修改成功");
    }

    /**
     * 修改用户状态
     * @param userId 用户ID
     * @param status 是否启用（0-禁用，1-启用）
     * @return 默认响应类
     */
    @Override
    public Result<?> updateUserStatus(Long userId, Integer status) {
        validateUserId(userId);
        validateStatus(status);

        if (sysUserMapper.updateUserStatus(userId, status) > 0) {
            log.error("用户状态修改失败，用户ID: {}，状态: {}", userId, status);
            throw new BusinessException("用户状态修改失败");
        }

        log.info("用户状态修改成功，ID: {}, Status: {}", userId, DefaultStatusEnum.getDesc(status));
        return Result.ok("用户状态修改成功");
    }

    /**
     * 获取用户列表
     * @param userDTO 用户传输类
     * @return 用户响应类集合
     */
    @Override
    public Result<List<SysUserVO>> listUser(SysUserDTO userDTO) {
        validateUserDTO(userDTO);

        SysUser user = convertToSysUser(userDTO);
        List<SysUser> users = sysUserMapper.listUser(user);
        List<SysUserVO> userVOs = ObjectConvertTool.originsConvert(users, SysUserVO.class);

        return Result.ok("查询成功", userVOs);
    }

    /**
     * 获取用户信息
     * @param userId 用户ID
     * @return 用户响应类
     */
    @Override
    public Result<SysUserVO> getUserInfo(Long userId) {
        return Optional.ofNullable(sysUserMapper.getUserById(userId))
                .map(user -> {
                    log.debug("成功获取用户信息，用户ID: {}", userId);
                    return Result.ok("查询成功", convertToSysUserVO(user));
                })
                .orElseGet(() -> {
                    log.warn("未查询到该用户，用户ID: {}", userId);
                    return Result.error("用户信息未找到");
                });
    }

    /**
     * TODO 消息与通知
     * @param userId 用户ID
     * @param type 信息或通知类型
     * @param message 内容
     * @return 默认响应类
     */
    @Override
    public Result<?> notifyUser(Long userId, String type, String message) {
        return null;
    }

    /**
     * TODO 密码强度检测优化
     * @param password 用户密码
     * @return 默认响应类
     */
    @Override
    public Result<?> detectPasswordSecurity(String password) {
        validatePassword(password);

        return Result.ok(PasswordStrengthValidator.validatePassword(password));
    }

    /**
     * 获取所有通知类型
     * @return 默认响应类
     */
    @Override
    public Result<?> getAllNotifType() {
        return Result.ok("获取成功", UserNotifyTypeEnum.getAllType());
    }

    //------------------------ 参数校验 ------------------------
    private void validateUserDTO(SysUserDTO dto) {
        if (Objects.isNull(dto)) {
            throw new BusinessException("用户信息不能为空");
        }
    }

    private void validUniqueUsername(SysUserDTO dto) {
        if (Objects.nonNull(sysUserMapper.getUserByUsername(dto.getUsername()))) {
            throw new BusinessException("用户名已存在");
        }
    }

    private void validateAuthenticationDTO(SysUserAuthenticationDTO dto) {
        if (Objects.isNull(dto) || Objects.isNull(dto.getId())) {
            throw new BusinessException("实名认证参数无效");
        }
        if (DefaultStatusEnum.ENABLED.getCode() != sysUserMapper.getUserById(dto.getId()).getStatus()) {
            throw new BusinessException("用户状态异常，无法认证");
        }
    }

    private void validateUserId(Long userId) {
        if (Objects.isNull(userId) || userId <= 0) {
            throw new BusinessException("用户ID无效");
        }
        if (Objects.isNull(sysUserMapper.getUserById(userId))) {
            throw new BusinessException("用户不存在");
        }
    }

    private void validateStatus(Integer status) {
        if (Objects.isNull(status)) {
            throw new BusinessException("状态值为空");
        }
        if (!DefaultStatusEnum.isValid(status)) {
            throw new BusinessException("无效的用户状态");
        }
    }

    private void validatePassword(String password) {
        if (Objects.isNull(password) || password.isEmpty()) {
            throw new BusinessException("用户密码无效");
        }
    }

    //------------------------ 工具方法  ------------------------
    // 将 DTO 转换为实体
    private SysUser convertToSysUser(SysUserDTO dto) {
        return ObjectConvertTool.originConvert(dto, SysUser.class);
    }

    // 将实体转换为 VO
    private SysUserVO convertToSysUserVO(SysUser entity) {
        return ObjectConvertTool.originConvert(entity, SysUserVO.class);
    }
}